package com.aihuishou.monitor;

import com.aihuishou.monitor.model.DefaultMessageTree;
import com.aihuishou.monitor.model.Event;
import com.aihuishou.monitor.model.Message;
import com.aihuishou.monitor.model.MessageParser;
import com.aihuishou.monitor.model.Transaction;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

@Slf4j
public class MessageThreadLocal {

    private static final ThreadLocal<Context> CONTEXT_THREAD_LOCAL = new ThreadLocal<>();
    private static final ThreadLocal<Exception> BIZ_ERROR = new ThreadLocal<>();
    private static final List<String> FILTER_URI = new ArrayList<>();

    static {
        FILTER_URI.add("/actuator/health");
    }

    public static Context getContext() {
        Context context = CONTEXT_THREAD_LOCAL.get();
        if (context == null) {
            context = new Context();
            CONTEXT_THREAD_LOCAL.set(context);
        }
        return context;
    }

    public static void setBizError(Exception ex) {
        BIZ_ERROR.set(ex);
    }

    public static Exception getBizError() {
        Exception exception = BIZ_ERROR.get();
        BIZ_ERROR.remove();
        return exception;
    }

    public static class Context {
        private final Stack<Transaction> stack;

        public Context() {
            this.stack = new Stack<>();
        }

        public void addMessage(Message message) {
            if (message instanceof Transaction) {
                Transaction t = (Transaction) message;
                if (stack.isEmpty()) {
                    stack.add(t);
                } else {
                    stack.peek().addChild(t);
                    stack.push(t);
                }
            } else if (message instanceof Event) {
                Event e = (Event) message;
                if (!stack.isEmpty()) {
                    stack.peek().addChild(e);
                }
            }
        }

        public void endMessage(Message message) {
            if (!stack.isEmpty() && message instanceof Transaction) {
                Transaction t = stack.peek();
                // 添加校验: 如果没匹配到，则一直弹栈匹配
                if (t == message) {
                    stack.pop();
                }
            }

            if (stack.isEmpty() && (message instanceof Event || message instanceof Transaction)) {
                try {
                    // 结束，处理埋点；打印特殊符号用作日志过滤
                    DefaultMessageTree tree = new DefaultMessageTree(message);
                    MessageParser.traverse(message, tree);

                    // 超长问题
//                String formatStr = MessageParser.getFormatStr(tree);
//                if (formatStr != null && LogConstants.TYPE_URL.equals(message.getType())
//                    && !FILTER_URI.contains(message.getName())) {
//                    log.info("==where-filter== ==log-start=={}==log-end==", formatStr);
//                }

                    if (LogConstants.TYPE_URL.equals(message.getType())
                        && FILTER_URI.stream().noneMatch(e -> message.getName().contains(e))) {
                        List<String> formatStrLimit = MessageParser.getFormatStrLimit(tree, 5);
                        for (String str : formatStrLimit) {
                            log.info("==where-filter== ==log-start=={}==log-end==", str);
                        }
                    }
                    if (Boolean.TRUE) {
                        String rootStr = MessageParser.getRootStr(message);
                        log.info("==where-root-filter== ==log-start=={}==log-end==", rootStr);
                    }
                } finally {
                    CONTEXT_THREAD_LOCAL.remove();
                }
            }
        }
    }
}
